/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tomasio.projects.lua.dao;

import com.tomasio.projects.lua.exception.DAOException;
import com.tomasio.projects.lua.model.Group;
import java.util.List;
import javax.naming.Name;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.query.LdapQuery;
import static org.springframework.ldap.query.LdapQueryBuilder.query;
import org.springframework.ldap.support.LdapNameBuilder;

/**
 *
 * @author fernandofot
 */
public class SpringLDAPGroupDAO implements GroupDAO {

    public static final String BASE_DN = "dc=decea,dc=intraer";

    private LdapTemplate ldapTemplate;

    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }

    @Override
    public String create(Group group) throws DAOException {
        DirContextAdapter context = new DirContextAdapter(buildDn(group));
        mapToContext(group, context);
        ldapTemplate.bind(context);
        return group.getUid();
    }

    @Override
    public void remove(String uid) throws DAOException {
        Group group = find(uid);
        ldapTemplate.unbind(buildDn(group));
    }

    @Override
    public void update(Group group) throws DAOException {
        Name dn = buildDn(group);
        DirContextOperations context = ldapTemplate.lookupContext(dn);
        mapToContext(group, context);
        ldapTemplate.modifyAttributes(context);
    }

    @Override
    public List<Group> findAll() throws DAOException {
        EqualsFilter filter = new EqualsFilter("objectclass", "organizationalUnit");
        Name applicationsPath = LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .build();
        return ldapTemplate.search(applicationsPath, filter.encode(), getContextMapper());

    }
    
    @Override
    public List<Group> findAll(String applicationUID) throws DAOException {
        EqualsFilter filter = new EqualsFilter("objectclass", "groupOfNames");
        Name applicationsPath = LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .add("ou", applicationUID)
                .build();
        return ldapTemplate.search(applicationsPath, filter.encode(), getContextMapper());

    }

    @Override
    public List<Group> search(String term) throws DAOException {
        EqualsFilter filter = new EqualsFilter("objectclass", "groupOfNames");
        Name applicationsPath = LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .build();
        return ldapTemplate.search(applicationsPath, filter.encode(), getContextMapper());

    }

    @Override
    public Group find(String uid) throws DAOException {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    protected ContextMapper getContextMapper() {
        return new GroupContextMapper();
    }

    protected Name buildDn(Group group) {
        return buildDn(group.getDescription());
    }

    protected Name buildDn(String name) {
        return LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .add("ou", name)
                .build();
    }

    protected void mapToContext(Group group, DirContextOperations context) {
        context.setAttributeValues("objectclass", new String[]{"groupOfNames"});
        context.setAttributeValue("desription", group.getDescription());
        context.setAttributeValue("cn", group.getName());

    }

    private static class GroupContextMapper extends AbstractContextMapper<Group> {

        @Override
        public Group doMapFromContext(DirContextOperations context) {
            Group g = new Group();
            g.setUid(context.getStringAttribute("cn"));
            g.setName(context.getStringAttribute("cn"));
            g.setDescription(context.getStringAttribute("description"));

            return g;
        }

    }
}
